package classification.calcSimilarity;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;

import org.dom4j.Document;
import org.dom4j.io.SAXReader;

import classification.elemListRepr.XMLElement;
import classification.elemListRepr.XMLElementList;

import preprocess.Arith;
import preprocess.XMLDoc;

/**
 * 该类继承自CalcSimilarity，实现了只考虑完全对应结构处文本相似度贡献的XML文档相似度计算
 * 
 * @author eDisOn
 * 
 */
public class CalcSimilarityByDiagonal extends CalcSimilarity
{

    /**
     * @see similarity.Similarity#calcSimilarity(preprocess.XMLDoc,
     *      preprocess.XMLDoc)
     */
    public double calcSimilarity(XMLDoc doc1, XMLDoc doc2)
    {
        double similarity = 0.0;

        XMLElementList firXMLELReprList = super.loadXMLEList(doc1);
        XMLElementList secXMLELReprList = super.loadXMLEList(doc2);

        /* 将这两个XMlelementList对象作为参数传入，计算相似度值 */
        similarity = this.calcSimilarity(firXMLELReprList, secXMLELReprList);

        return similarity;
    }

    /**
     * 计算两个XMLElementList所表示的XML文档的相似度
     * 
     * @param list1
     *            待计算的第一个XMLElementList对象
     * @param list2
     *            待计算的第二个XMLElementList对象
     * 
     * @return 所指定的两个XMLElementList对象所表示的XML文档的相似度
     */
    private double calcSimilarity(XMLElementList list1, XMLElementList list2)
    {
        XMLElementList firXMLELReprList = list1;
        XMLElementList secXMLELReprList = list2;

        int firListVocNum = list1.getTotalVocNum();
        int secListVocNum = list2.getTotalVocNum();

        double similarity = 0.0;
        for (Iterator firIt = firXMLELReprList.Iterator(), secIt = secXMLELReprList
                .Iterator(); firIt.hasNext() && secIt.hasNext();)
        {
            /*
             * calculate similarity between two matched element in two xml
             * document
             */
            double elemSimilarity = 0.0;

            XMLElement firElem = (XMLElement) firIt.next();
            XMLElement secElem = (XMLElement) secIt.next();

            HashMap<String, Double> firVocList = firElem.getVocabularyList();
            HashMap<String, Double> secVocList = secElem.getVocabularyList();

            if (firVocList != null && secVocList != null)
            {
                Set<String> firKeySet = firVocList.keySet();
                for (Iterator<String> firVocIt = firKeySet.iterator(); firVocIt
                        .hasNext();)
                {
                    String firKey = firVocIt.next();
                    double firValue = firVocList.get(firKey);
                    if (secVocList.containsKey(firKey))
                    {
                        double secValue = secVocList.get(firKey);
                        elemSimilarity += firValue * secValue;
                    }
                }

                /*
                 * add the element similarity to total similarity for two xml
                 * document
                 */
                double proportion1 = ((double) firElem.getVocNum() / (double) firListVocNum);
                double proportion2 = ((double) secElem.getVocNum() / (double) secListVocNum);
                double proportion = proportion1 * proportion2;

                similarity += elemSimilarity * proportion;
            }
        }

        return Arith.round(similarity, 8);
    }

}
